'use no memo';

import { TransactionMeta } from '@metamask/transaction-controller';
import { CaipChainId, Hex } from '@metamask/utils';
import { useMemo } from 'react';
import { useSelector } from 'react-redux';

import { sumHexes } from '../../../../../../shared/modules/conversion.utils';
import {
  AlertActionKey,
  RowAlertKey,
} from '../../../../../components/app/confirm/info/row/constants';
import { Alert } from '../../../../../ducks/confirm-alerts/confirm-alerts';
import { Severity } from '../../../../../helpers/constants/design-system';
import { useI18nContext } from '../../../../../hooks/useI18nContext';
import {
  getMultichainNetworkConfigurationsByChainId,
  getNativeTokenCachedBalanceByChainIdByAccountAddress,
  getUseTransactionSimulations,
  selectTransactionFeeById,
} from '../../../../../selectors';
import { useConfirmContext } from '../../../context/confirm';
import { isBalanceSufficient } from '../../../send-legacy/send.utils';
import { useIsGaslessSupported } from '../../gas/useIsGaslessSupported';

export function useInsufficientBalanceAlerts({
  ignoreGasFeeToken,
}: {
  ignoreGasFeeToken?: boolean;
} = {}): Alert[] {
  const t = useI18nContext();
  const { currentConfirmation } = useConfirmContext<TransactionMeta>();
  const {
    id: transactionId,
    chainId,
    selectedGasFeeToken,
    gasFeeTokens,
    txParams: { value = '0x0', from: fromAddress = '' } = {},
  } = currentConfirmation ?? {};

  const batchTransactionValues =
    currentConfirmation?.nestedTransactions?.map(
      (trxn) => (trxn.value as Hex) ?? 0x0,
    ) ?? [];

  const isSimulationEnabled = useSelector(getUseTransactionSimulations);

  const chainBalances = useSelector((state) =>
    getNativeTokenCachedBalanceByChainIdByAccountAddress(
      state,
      fromAddress ?? '',
    ),
  ) as Record<Hex, Hex>;

  const balance = chainBalances?.[chainId as Hex] ?? '0x0';

  const totalValue = sumHexes(value, ...batchTransactionValues);

  const { hexMaximumTransactionFee } = useSelector((state) =>
    selectTransactionFeeById(state, transactionId),
  );

  const [multichainNetworks, evmNetworks] = useSelector(
    getMultichainNetworkConfigurationsByChainId,
  );

  const nativeCurrency = (
    multichainNetworks[chainId as CaipChainId] ?? evmNetworks[chainId]
  )?.nativeCurrency;

  const insufficientBalance = !isBalanceSufficient({
    amount: totalValue,
    gasTotal: hexMaximumTransactionFee,
    balance,
  });

  const isSponsored = currentConfirmation?.isGasFeeSponsored;
  const { isSupported: isGaslessSupported } = useIsGaslessSupported();
  const isSponsoredTransaction = isSponsored && isGaslessSupported;

  const canSkipSimulationChecks = ignoreGasFeeToken || !isSimulationEnabled;
  const hasGaslessSimulationFinished =
    canSkipSimulationChecks || Boolean(gasFeeTokens);

  const showAlert =
    insufficientBalance &&
    hasGaslessSimulationFinished &&
    (ignoreGasFeeToken || !selectedGasFeeToken) &&
    !isSponsoredTransaction;

  return useMemo(() => {
    if (!showAlert) {
      return [];
    }

    return [
      {
        actions: [
          {
            key: AlertActionKey.Buy,
            label: t('alertActionBuyWithNativeCurrency', [nativeCurrency]),
          },
        ],
        field: RowAlertKey.EstimatedFee,
        isBlocking: true,
        key: 'insufficientBalance',
        message: t('alertMessageInsufficientBalanceWithNativeCurrency', [
          nativeCurrency,
        ]),
        reason: t('alertReasonInsufficientBalance'),
        severity: Severity.Danger,
      },
    ];
  }, [nativeCurrency, showAlert, t]);
}
